package com.recruit.business.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.recruit.common.model.*;
import com.recruit.common.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@Slf4j
@RestController
@RequestMapping("/recruit/ct")
public class CtController {

    @Autowired
    private CtService ctService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private PositionService positionService;

    @Autowired
    private CompanyService companyService;

    @Autowired
    private UserService userService;

    @Resource
    RedisTemplate redisTemplate;


    /**
     * 职位总数、入驻企业总数、企业招聘者总数、应聘者总数-综合统计
     *
     * @return
     */
    @RequestMapping(value = "/total", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public TotalDO total() {
        // 定义缓存键
        String key = "totalData";
        TotalDO totalDO = null;

        // 尝试从 Redis 缓存中读取
        Object cachedJson = redisTemplate.opsForValue().get(key);
        if (cachedJson != null) {
            log.info("从 Redis 缓存中获取数据");
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                // 将缓存中的 JSON 字符串反序列化为 TotalDO 对象
                totalDO = objectMapper.readValue(cachedJson.toString(), TotalDO.class);
            } catch (JsonProcessingException e) {
                // 如果反序列化失败，记录日志并重新计算数据
                log.error("Failed to deserialize TotalDO from Redis cache", e);
            }
        }

        // 如果缓存中没有数据，或者反序列化失败，则重新计算数据
        if (totalDO == null) {
            // 职位总数
            QueryWrapper<PositionDO> posWrapper = new QueryWrapper<>();
            posWrapper.isNull("delete_time");
            Integer posNum = positionService.count(posWrapper);

            // 入驻企业总数
            QueryWrapper<CompanyDO> companyWrapper = new QueryWrapper<>();
            companyWrapper.isNull("delete_time");
            Integer companyNum = companyService.count(companyWrapper);

            // 企业招聘者总数
            Integer hrNum = userService.countByGroupId(3);

            // 应聘者总数
            Integer userNum = userService.countByGroupId(4);

            // 创建 TotalDO 对象
            totalDO = new TotalDO();
            totalDO.setPosNum(posNum);
            totalDO.setCompanyNum(companyNum);
            totalDO.setHrNum(hrNum);
            totalDO.setUserNum(userNum);

            // 将 TotalDO 对象序列化为 JSON 字符串并存储到 Redis，设置过期时间为1天
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                String json = objectMapper.writeValueAsString(totalDO);
                redisTemplate.opsForValue().set(key, json, 1, TimeUnit.DAYS);
            } catch (JsonProcessingException e) {
                // 如果序列化失败，记录日志但不影响返回结果
                log.error("Failed to serialize TotalDO to JSON", e);
            }
        }

        // 返回 TotalDO 对象
        return totalDO;
    }

    /**
     * 各分类的数量占比，各个分类岗位数量。
     *
     * @return
     */
    @RequestMapping(value = "/posCt", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public List<PosCtDO> posCt() {
        // 查询缓存
        List<String> PosCtDOCache = redisTemplate.opsForList().range("posCt", 0, -1);

        List<PosCtDO> result;

        // 如果缓存存在且不为空
        if (PosCtDOCache != null && !PosCtDOCache.isEmpty()) {
            log.info("从 Redis 缓存中获取数据");
            // 将缓存中的 JSON 字符串反序列化为对象列表
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                result = PosCtDOCache.stream()
                        .map(json -> {
                            try {
                                return objectMapper.readValue(json, PosCtDO.class);
                            } catch (JsonProcessingException e) {
                                throw new RuntimeException("Failed to deserialize PosAddCtDO", e);
                            }
                        })
                        .collect(Collectors.toList());
            } catch (Exception e) {
                throw new RuntimeException("Failed to parse cached data", e);
            }
        } else {
            // 如果缓存中没有，从数据库中获取数据
            result = categoryService.posCount();

            // 将查询结果序列化为 JSON 字符串并存入缓存
            if (result != null && !result.isEmpty()) {
                ObjectMapper objectMapper = new ObjectMapper();
                List<String> serializedList = result.stream()
                        .map(item -> {
                            try {
                                return objectMapper.writeValueAsString(item);
                            } catch (JsonProcessingException e) {
                                throw new RuntimeException("Failed to serialize PosCtDO", e);
                            }
                        })
                        .collect(Collectors.toList());

                // 将序列化后的数据存入 Redis
                redisTemplate.opsForList().leftPushAll("posCt", serializedList);
                // 设置缓存过期时间为一天
                redisTemplate.expire("posCt", 1, TimeUnit.DAYS);
            }
        }

        return result;

    }


    /**
     * 新增职位数随时间变化的动态曲线图（按周、月、90天，180天、一年切换）
     *
     * @return
     */
    @RequestMapping(value = "/posAddCt", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public List<PosAddCtDO> posAddCt(Integer dayNum) {
        // 查询缓存
        List<String> posAddCtCache = redisTemplate.opsForList().range("posAddCt", 0, -1);

        List<PosAddCtDO> result;

        // 如果缓存存在且不为空
        if (posAddCtCache != null && !posAddCtCache.isEmpty()) {
            log.info("从 Redis 缓存中获取数据");
            // 将缓存中的 JSON 字符串反序列化为对象列表
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                result = posAddCtCache.stream()
                        .map(json -> {
                            try {
                                return objectMapper.readValue(json, PosAddCtDO.class);
                            } catch (JsonProcessingException e) {
                                throw new RuntimeException("Failed to deserialize PosAddCtDO", e);
                            }
                        })
                        .collect(Collectors.toList());
            } catch (Exception e) {
                throw new RuntimeException("Failed to parse cached data", e);
            }
        } else {
            // 如果缓存不存在或为空，查询数据库
            result = positionService.posAddCt(dayNum);

            // 将查询结果序列化为 JSON 字符串并存入缓存
            if (result != null && !result.isEmpty()) {
                ObjectMapper objectMapper = new ObjectMapper();
                List<String> serializedList = result.stream()
                        .map(item -> {
                            try {
                                return objectMapper.writeValueAsString(item);
                            } catch (JsonProcessingException e) {
                                throw new RuntimeException("Failed to serialize PosAddCtDO", e);
                            }
                        })
                        .collect(Collectors.toList());

                // 将序列化后的数据存入 Redis
                redisTemplate.opsForList().leftPushAll("posAddCt", serializedList);
                // 设置缓存过期时间为一天
                redisTemplate.expire("posAddCt", 1, TimeUnit.DAYS);
            }
        }

        return result;
    }

    /**
     * 获取公司列表
     *
     * @return
     */
    @RequestMapping(value = "/companyList", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public List<CompanyDO> companyList(Integer companyId) {
        // 缓存键
        String cacheKey = "companyList";

        // 查询缓存
        List<String> cachedCompanyList = redisTemplate.opsForList().range(cacheKey, 0, -1);

        List<CompanyDO> result;

        // 如果缓存存在且不为空
        if (cachedCompanyList != null && !cachedCompanyList.isEmpty()) {
            log.info("从 Redis 缓存中获取数据");
            // 将缓存中的 JSON 字符串反序列化为 CompanyDO 对象列表
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                result = cachedCompanyList.stream()
                        .map(json -> {
                            try {
                                return objectMapper.readValue(json, CompanyDO.class);
                            } catch (JsonProcessingException e) {
                                throw new RuntimeException("Failed to deserialize CompanyDO", e);
                            }
                        })
                        .collect(Collectors.toList());
            } catch (Exception e) {
                throw new RuntimeException("Failed to parse cached data", e);
            }
        } else {
            // 如果缓存不存在或为空，查询数据库
            result = companyService.list();

            // 将查询结果序列化为 JSON 字符串并存入缓存
            if (result != null && !result.isEmpty()) {
                ObjectMapper objectMapper = new ObjectMapper();
                List<String> serializedList = result.stream()
                        .map(item -> {
                            try {
                                return objectMapper.writeValueAsString(item);
                            } catch (JsonProcessingException e) {
                                throw new RuntimeException("Failed to serialize CompanyDO", e);
                            }
                        })
                        .collect(Collectors.toList());

                // 将序列化后的数据存入 Redis
                redisTemplate.opsForList().leftPushAll(cacheKey, serializedList);
                // 设置缓存过期时间为一天
                redisTemplate.expire(cacheKey, 1, TimeUnit.DAYS);
            }
        }

        return result;
    }

    /**
     * 企业内各个分类下的职位需求数雷达图。
     *
     * @return
     */
    @RequestMapping(value = "/posByCompanyCt", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public List<PosCtDO> posByCompanyCt(Integer companyId) {
        // 定义缓存键，根据companyId动态生成
        String cacheKey = "posByCompanyCt:" + companyId;

        // 查询缓存
        List<String> cachedList = redisTemplate.opsForList().range(cacheKey, 0, -1);

        List<PosCtDO> result;

        // 如果缓存存在且不为空
        if (cachedList != null && !cachedList.isEmpty()) {
            // 将缓存中的 JSON 字符串反序列化为 PosCtDO 对象列表
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                result = cachedList.stream()
                        .map(json -> {
                            try {
                                return objectMapper.readValue(json, PosCtDO.class);
                            } catch (JsonProcessingException e) {
                                throw new RuntimeException("Failed to deserialize PosCtDO", e);
                            }
                        })
                        .collect(Collectors.toList());
            } catch (Exception e) {
                throw new RuntimeException("Failed to parse cached data", e);
            }
        } else {
            // 如果缓存不存在或为空，查询数据库
            result = categoryService.posByCompanyCt(companyId);

            // 将查询结果序列化为 JSON 字符串并存入缓存
            if (result != null && !result.isEmpty()) {
                ObjectMapper objectMapper = new ObjectMapper();
                List<String> serializedList = result.stream()
                        .map(item -> {
                            try {
                                return objectMapper.writeValueAsString(item);
                            } catch (JsonProcessingException e) {
                                throw new RuntimeException("Failed to serialize PosCtDO", e);
                            }
                        })
                        .collect(Collectors.toList());

                // 将序列化后的数据存入 Redis
                redisTemplate.opsForList().leftPushAll(cacheKey, serializedList);
                // 设置缓存过期时间为一天
                redisTemplate.expire(cacheKey, 1, TimeUnit.DAYS);
            }
        }

        return result;

    }


    /**
     * 每个企业内的岗位总数。
     *
     * @return
     */
    @RequestMapping(value = "/posCompanyCt", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public List<PosComCtDO> posCompanyCt() {
        // 定义缓存键
        String cacheKey = "posCompanyCt";

        // 查询缓存
        List<String> cachedList = redisTemplate.opsForList().range(cacheKey, 0, -1);

        List<PosComCtDO> result;

        // 如果缓存存在且不为空
        if (cachedList != null && !cachedList.isEmpty()) {
            // 将缓存中的 JSON 字符串反序列化为 PosComCtDO 对象列表
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                result = cachedList.stream()
                        .map(json -> {
                            try {
                                return objectMapper.readValue(json, PosComCtDO.class);
                            } catch (JsonProcessingException e) {
                                throw new RuntimeException("Failed to deserialize PosComCtDO", e);
                            }
                        })
                        .collect(Collectors.toList());
            } catch (Exception e) {
                throw new RuntimeException("Failed to parse cached data", e);
            }
        } else {
            // 如果缓存不存在或为空，查询数据库
            result = positionService.posCompanyCt();

            // 将查询结果序列化为 JSON 字符串并存入缓存
            if (result != null && !result.isEmpty()) {
                ObjectMapper objectMapper = new ObjectMapper();
                List<String> serializedList = result.stream()
                        .map(item -> {
                            try {
                                return objectMapper.writeValueAsString(item);
                            } catch (JsonProcessingException e) {
                                throw new RuntimeException("Failed to serialize PosComCtDO", e);
                            }
                        })
                        .collect(Collectors.toList());

                // 将序列化后的数据存入 Redis
                redisTemplate.opsForList().leftPushAll(cacheKey, serializedList);
                // 设置缓存过期时间为一天
                redisTemplate.expire(cacheKey, 1, TimeUnit.DAYS);
            }
        }

        return result;

    }

    /**
     * 各个职位的浏览量随时间的动态柱状。
     *
     * @return
     */
    @RequestMapping(value = "/posClkCt", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public List<List<String>> posClkCt() {
        //[{"id":null,"title":"Java工程师","dt":"2021-12-16","clk_num":2},{"id":null,"title":"python游戏工程师","dt":"2021-12-16","clk_num":1}]
        // 定义缓存键
        String cacheKey = "posClkCt";

        // 查询缓存
        List<String> cachedList = redisTemplate.opsForList().range(cacheKey, 0, -1);

        List<List<String>> result;

        // 如果缓存存在且不为空
        if (cachedList != null && !cachedList.isEmpty()) {
            // 将缓存中的 JSON 字符串反序列化为 List<List<String>> 格式
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                // 使用 TypeReference 明确指定目标类型
                result = objectMapper.readValue(
                        "[" + String.join(",", cachedList) + "]",
                        new TypeReference<List<List<String>>>() {
                        }
                );
            } catch (Exception e) {
                throw new RuntimeException("Failed to parse cached data", e);
            }
        } else {
            // 如果缓存不存在或为空，查询数据库
            List<PosClkCtDO> listR = positionService.posClkCt();

            // 转换为 List<List<String>> 格式
            List<List<String>> s = new ArrayList<>();
            List<String> header = new ArrayList<>();
            header.add("Income");
            header.add("Life Expectancy");
            header.add("Population");
            header.add("Country");
            header.add("Year");
            s.add(header);

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            for (PosClkCtDO d : listR) {
                List<String> list = new ArrayList<>();
                list.add(String.valueOf(d.getClkNum()));
                list.add(String.valueOf(d.getClkNum()) + "222");
                list.add(String.valueOf(d.getClkNum()) + "333");
                list.add(d.getTitle());
                String dateString = sdf.format(d.getDt());
                list.add(dateString);
                s.add(list);
            }

            // 将结果序列化为 JSON 字符串并存入缓存
            if (s != null && !s.isEmpty()) {
                ObjectMapper objectMapper = new ObjectMapper();
                List<String> serializedList = s.stream()
                        .map(item -> {
                            try {
                                return objectMapper.writeValueAsString(item);
                            } catch (JsonProcessingException e) {
                                throw new RuntimeException("Failed to serialize List<List<String>>", e);
                            }
                        })
                        .collect(Collectors.toList());

                // 将序列化后的数据存入 Redis
                redisTemplate.opsForList().leftPushAll(cacheKey, serializedList);
                // 设置缓存过期时间为一天
                redisTemplate.expire(cacheKey, 1, TimeUnit.DAYS);
            }

            result = s;
        }

        return result;
    }

    /**
     * 职位动态走势图一条曲线是系统职位总数,其他曲线是各个企业的
     *
     * @return
     */
    @RequestMapping(value = "/posDongCt", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public Map<String, Object> posDongCt() {

        List<String> titleList = new ArrayList<String>();
        //[{"id":null,"title":"Java工程师","dt":"2021-12-16","clk_num":2},{"id":null,"title":"python游戏工程师","dt":"2021-12-16","clk_num":1}]
        List<PosDongCtDO> listR = positionService.posDongCt();

        List<List<String>> s = new ArrayList<List<String>>();
        List<String> l1 = new ArrayList<String>();
        l1.add("Income");
        l1.add("Life Expectancy");
        l1.add("Population");
        l1.add("Country");
        l1.add("Year");
        s.add(l1);

        for (PosDongCtDO d : listR) {
            List<String> list = new ArrayList<String>();
            list.add(String.valueOf(d.getNum()));
            list.add(String.valueOf(d.getNum()) + "222");
            list.add(String.valueOf(d.getNum()) + "333");
            list.add(d.getTitle());

            if (!titleList.contains(d.getTitle())) {
                titleList.add(d.getTitle());
            }


            list.add(String.valueOf(d.getDt()));

            s.add(list);
        }

        Map<String, Object> map = new HashMap<String, Object>();
        map.put("list", s);
        map.put("titleList", titleList);

        return map;
    }

    /**
     * 查询所有友情链接
     *
     * @return
     */
    @RequestMapping(value = "/ct", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public List<List<String>> ct() {
        // 定义缓存键
        String cacheKey = "ctData";

        // 查询缓存
        List<String> cachedData = redisTemplate.opsForList().range(cacheKey, 0, -1);

        List<List<String>> result;

        // 如果缓存存在且不为空
        if (cachedData != null && !cachedData.isEmpty()) {
            // 将缓存中的 JSON 字符串反序列化为 List<List<String>> 格式
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                // 使用 TypeReference 明确指定目标类型
                TypeReference<List<List<String>>> typeRef = new TypeReference<List<List<String>>>() {
                };
                result = objectMapper.readValue("[" + String.join(",", cachedData) + "]", typeRef);
            } catch (Exception e) {
                throw new RuntimeException("Failed to parse cached data", e);
            }
            return result;
        } else {
            List<List<String>> s = new ArrayList<>();
            List<String> l10 = new ArrayList<String>();
            l10.add("Income");
            l10.add("Life Expectancy");
            l10.add("Population");
            l10.add("Country");
            l10.add("Year");
            List<String> l11 = new ArrayList<String>();
            l11.add("11");
            l11.add("111");
            l11.add("11");
            l11.add("Country11");
            l11.add("1111");
            List<String> l12 = new ArrayList<String>();
            l12.add("12");
            l12.add("121");
            l12.add("12");
            l12.add("Country12");
            l12.add("1212");
            List<String> l13 = new ArrayList<String>();
            l13.add("13");
            l13.add("131");
            l13.add("13");
            l13.add("Country13");
            l13.add("1313");
            List<String> l14 = new ArrayList<String>();
            l14.add("14");
            l14.add("141");
            l14.add("14");
            l14.add("Country14");
            l14.add("1414");
            List<String> l15 = new ArrayList<String>();
            l15.add("15");
            l15.add("151");
            l15.add("15");
            l15.add("Country15");
            l15.add("1515");
            List<String> l16 = new ArrayList<String>();
            l16.add("16");
            l16.add("161");
            l16.add("16");
            l16.add("Country16");
            l16.add("1616");
            List<String> l17 = new ArrayList<String>();
            l17.add("17");
            l17.add("171");
            l17.add("17");
            l17.add("Country17");
            l17.add("1717");
            List<String> l18 = new ArrayList<String>();
            l18.add("18");
            l18.add("181");
            l18.add("18");
            l18.add("Country18");
            l18.add("1818");
            List<String> l19 = new ArrayList<String>();
            l19.add("19");
            l19.add("191");
            l19.add("19");
            l19.add("Country19");
            l19.add("1919");
            List<String> l20 = new ArrayList<String>();
            l20.add("20");
            l20.add("202");
            l20.add("20");
            l20.add("Country20");
            l20.add("2020");
            List<String> l21 = new ArrayList<String>();
            l21.add("21");
            l21.add("212");
            l21.add("21");
            l21.add("Country21");
            l21.add("2121");
            List<String> l22 = new ArrayList<String>();
            l22.add("22");
            l22.add("222");
            l22.add("22");
            l22.add("Country22");
            l22.add("2222");
            List<String> l23 = new ArrayList<String>();
            l23.add("23");
            l23.add("232");
            l23.add("23");
            l23.add("Country23");
            l23.add("2323");
            List<String> l24 = new ArrayList<String>();
            l24.add("24");
            l24.add("242");
            l24.add("24");
            l24.add("Country24");
            l24.add("2424");
            List<String> l25 = new ArrayList<String>();
            l25.add("25");
            l25.add("252");
            l25.add("25");
            l25.add("Country25");
            l25.add("2525");
            List<String> l26 = new ArrayList<String>();
            l26.add("26");
            l26.add("262");
            l26.add("26");
            l26.add("Country26");
            l26.add("2626");
            List<String> l27 = new ArrayList<String>();
            l27.add("27");
            l27.add("272");
            l27.add("27");
            l27.add("Country27");
            l27.add("2727");
            List<String> l28 = new ArrayList<String>();
            l28.add("28");
            l28.add("282");
            l28.add("28");
            l28.add("Country28");
            l28.add("2828");
            List<String> l29 = new ArrayList<String>();
            l29.add("29");
            l29.add("292");
            l29.add("29");
            l29.add("Country29");
            l29.add("2929");
            List<String> l30 = new ArrayList<String>();
            l30.add("30");
            l30.add("303");
            l30.add("30");
            l30.add("Country30");
            l30.add("3030");
            List<String> l31 = new ArrayList<String>();
            l31.add("31");
            l31.add("313");
            l31.add("31");
            l31.add("Country31");
            l31.add("3131");
            List<String> l32 = new ArrayList<String>();
            l32.add("32");
            l32.add("323");
            l32.add("32");
            l32.add("Country32");
            l32.add("3232");
            List<String> l33 = new ArrayList<String>();
            l33.add("33");
            l33.add("333");
            l33.add("33");
            l33.add("Country33");
            l33.add("3333");
            List<String> l34 = new ArrayList<String>();
            l34.add("34");
            l34.add("343");
            l34.add("34");
            l34.add("Country34");
            l34.add("3434");
            List<String> l35 = new ArrayList<String>();
            l35.add("35");
            l35.add("353");
            l35.add("35");
            l35.add("Country35");
            l35.add("3535");

            s.add(l10);
            s.add(l11);
            s.add(l12);
            s.add(l13);
            s.add(l14);
            s.add(l15);
            s.add(l16);
            s.add(l17);
            s.add(l18);
            s.add(l19);
            s.add(l20);
            s.add(l21);
            s.add(l22);
            s.add(l23);
            s.add(l24);
            s.add(l25);
            s.add(l26);
            s.add(l27);
            s.add(l28);
            s.add(l29);
            s.add(l30);
            s.add(l31);
            s.add(l32);
            s.add(l33);
            s.add(l34);
            s.add(l35);

            //
            // 将生成的数据序列化为 JSON 字符串并存入缓存
            ObjectMapper objectMapper = new ObjectMapper();
            List<String> serializedData = s.stream()
                    .map(item -> {
                        try {
                            return objectMapper.writeValueAsString(item);
                        } catch (JsonProcessingException e) {
                            throw new RuntimeException("Failed to serialize List<List<String>>", e);
                        }
                    })
                    .collect(Collectors.toList());

            // 将序列化后的数据存入 Redis
            redisTemplate.opsForList().leftPushAll(cacheKey, serializedData);
            // 设置缓存过期时间为一天
            redisTemplate.expire(cacheKey, 1, TimeUnit.DAYS);
            return s;
        }
    }


}
